package com.bj58.groupbuy.action.threads;

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import com.bj58.groupbuy.action.model.IRReport;
import com.bj58.groupbuy.action.model.UserSubMailVo;
import com.bj58.groupbuy.action.service.IRReportService;
import com.bj58.groupbuy.action.service.IntReportMainService;
import com.bj58.groupbuy.action.service.UserSubMailService;
import com.bj58.groupbuy.action.util.DateUtil;
import com.bj58.groupbuy.action.util.ExcelUtilNew;
import com.bj58.groupbuy.action.util.FileUtil;
import com.bj58.groupbuy.action.util.MailUtil;
import com.bj58.groupbuy.action.util.ScfUtil;
import com.bj58.groupbuy.action.util.ZipUtil;
import com.bj58.groupbuy.service.locator.ServiceLocator;
import com.bj58.groupbuy.util.PathUtil;
import com.bj58.groupbuy.wf.page.Paginate;
/**
 * 不断的监听，一个一个的运行
 * 监测状态，如果运行完了，继续查询，不停的查询，如果查询为空就sleep
 * 可以由用户触发，当点击下载的时候触发，如果在运行就等待，如果不在运行就启动
 * */
public class UserSubEmailThread  extends Thread{
	private IRReportService iRReportService = ServiceLocator.get(IRReportService.class);
	private IntReportMainService intReportMainService = ServiceLocator.get(IntReportMainService.class);
	private UserSubMailService iRSubMailService = ServiceLocator.get(UserSubMailService.class);
	
	public static AtomicInteger threadDoneCount = new AtomicInteger();
	
	private UserSubMailVo irsm;
	
	public UserSubEmailThread(UserSubMailVo irsm){
		this.irsm = irsm;
	}

	public void run(){
		try {
			System.out.println("Thead  "+this.getId()+" begin to deal subMail ,ID  is" + irsm.getId());
			int result = sendSubMail(irsm);
			if(result == 2){
				irsm.setModTime(DateUtil.getStringDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
				iRSubMailService.updateVo(irsm);
			}
			System.out.println("Thead  "+this.getId()+" is end ");
			threadDoneCount.getAndIncrement(); //线程完成则在原子计数器上+1
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	
	/**用户下载邮件发送
	 * @param vo
	 * @return  邮件发送结果 	0 : 邮件发送失败  1：数据集为空   2：发送成功
	 */
	@SuppressWarnings("static-access")
	private int sendSubMail(UserSubMailVo vo){
		try {
			/**step 1.根据订阅的发送频率替换查询条件中的日期段参数
			 *  step 2.查询全部数据
			 *  step 3.判断数据结果内容大小，读取模板，选择以正文/EXCEL压缩附件发送；若超大则提示过大，发送提示内容。
			 */
			//step 1
			StringBuffer searchCondition=new StringBuffer();
			String condition = vo.getSearchCondition();
			String hasComp="";
			int dayRatio=vo.getDayRatio(); //环同比标志:1包含，0不包含
			int weekRatio=vo.getWeekRatio();
			String specialValue=vo.getSearchSpeValue();
			//日期列名称,从specialValue中获取
			
			String dateCol=specialValue.substring(specialValue.lastIndexOf(":")+1,specialValue.length()-1).trim();
			String startDate=specialValue.split(";")[0].split(":")[1];
			String endDate=specialValue.split(";")[1].split(":")[1];
			Date nowDate=new Date();
			searchCondition.append(" and "+dateCol+">='"+startDate+"'");
			searchCondition.append(" and "+dateCol+"<='"+endDate+"' ");
			searchCondition.append(condition);		
			//step 2
			IRReport irReport = iRReportService.getById(vo.getReportId());
			List<String> cols = new ArrayList<String>(); //查询字段项 -英文
			String gbs[] = null;
			if(!"".equals(vo.getSearchGroupBy())){//groupBy占位
				gbs=vo.getSearchGroupBy().split(",");
				cols.add("groupBy");
			}
			for(String col : vo.getSearchCols().split("&")){
				if(!"".equals(col)){
					cols.add(col);
				}
			}
			
			List<String> titleList = new ArrayList<String>(); //查询字段项 - 中文 表格TITLE
			for(String title : vo.getSearchTitles().split("&")){
				if(!"".equals(title)){
					titleList.add(title);
				}
			}
			//使用原special，不做任何更改
			Paginate<String> pList = intReportMainService.IRsearchValues(irReport, searchCondition.toString(), cols,null, vo.getSearchOrderBy(), vo.getSearchGroupBy(), 20, -1,specialValue,1);
			//step 3
				//收件人地址
			String[] emailAdds = vo.getSendEmail().split("/");
			//标题
			String titleDates = " ";
			if(startDate.equals(endDate)){
				titleDates = startDate;
			}else{
				titleDates = " from "+startDate +" to " + endDate;
			}
			if(titleDates=="")
			{
				titleDates=DateUtil.getStringDate(nowDate,"yyyy-MM-dd");
			}
			String emailTitle= "商业数据分析系统 - 报表邮件下载 - "+vo.getReportName()+titleDates;
			//正文内容
			String content = "数据请请参考附件。";
			//附件地址
			ArrayList<String>  attachedFileList =  new ArrayList<String>();
			int maxSendRows = 1500000; // 发送最大的数据行
			// 数据量不超标
			if(pList.getItems().size() < maxSendRows){//写EXCEL保存 并压缩
				SXSSFWorkbook wwb =new SXSSFWorkbook(10000);//内存中保留 10000 条数据，以免内存溢出，其余写入 硬盘
				HashMap<String, String> keyValue = new HashMap<String, String>();
				List<String> toSendItems = pList.getItems(); // 要发送的结果
				if (dayRatio == 1 || weekRatio == 1){
					toSendItems = new ArrayList<String>();
					// 含同环比
					if (dayRatio == 1) {
						hasComp += "dayRatio";
						
					}
					if (weekRatio == 1) {
						hasComp += ",weekRatio";
						
					}
					List<String> items = pList.getItems(); // 获得总结果集
					for (String recode : items) { // 对每一条记录提取维度值，放入对应的Map中
						StringBuilder key = new StringBuilder();
						String cells[] = recode.split(";", gbs.length + 1);
						for (int i = 0; i < gbs.length; i++) { // 维度
							key.append(cells[i].split(",")[0]);
							if (i + 1 < gbs.length)
								key.append("_");
						}
						String date = cells[0].split(",")[0];// 日期
						if (date.compareTo(startDate) >= 0&& date.compareTo(endDate) <= 0)
							toSendItems.add(recode);
						keyValue.put(key.toString(), cells[gbs.length]);
					}
				}
				if (null == toSendItems || toSendItems.isEmpty()) { // 要发送的数据集为空
					System.out.println("Send ReportSubEmail Fail! The  Datas is null, The SubMail  ID is "+ vo.getId());
					MailUtil.javaMailSend("下载邮件数据为空", "订阅ID为" + vo.getId(),"houzuoxin@58.com", null);
					return 1;
				}
				// 文件夹路径
				String dirPath = PathUtil.getWFNamespaceFolder()+ "/ReportSubMail" + "/SubMail-" + vo.getId() + "-"+ titleDates;
				String excelPath = dirPath + "/SubMail-" + vo.getId() + "-"+ titleDates + ".xlsx";
				File file = new File(dirPath);
				if (file.exists() && file.isDirectory()) {
					FileUtil.deleteDirectory(dirPath);
				}
				file.mkdirs();
				int statgbsindex=0;
				if(null !=gbs)
				{
					for (int i = 0; i < gbs.length; i++) { // 日期维度所在位置
						if (gbs[i].equals("stat_date")||gbs[i].equals("statDate")||gbs[i].equals("vDate")) {
							statgbsindex=i;
							break;
						}
					}
				}
				if ((dayRatio == 1 || weekRatio == 1) && gbs != null){	
					
					wwb = ExcelUtilNew.writeExcelCommonWithRatioSync(vo.getReportName() + titleDates, null, titleList,toSendItems, keyValue, gbs.length, excelPath,dayRatio == 1 ? true : false, weekRatio == 1 ? true:false,statgbsindex);
				}else{
					int gbLength = 0 ;
					if(null != gbs ){
						gbLength = gbs.length;
					}
					System.out.println("TTTTTTTTT");
					wwb = ExcelUtilNew.writeExcelCommonWithRatioSync(vo.getReportName()+ titleDates, null, titleList, toSendItems,null,gbLength,excelPath,false,false,statgbsindex);
					System.out.println("TTTTTTTTT1");
				}
				
					
				if(wwb==null){
					FileUtil.deleteDirectory(dirPath);
					return 1;
				}
				else{
					
					FileOutputStream os = new FileOutputStream(excelPath);
					System.out.println("TTTTTTTTT2");
					wwb.write(os);
					System.out.println("TTTTTTTTT3");
					os.close();
				}
				
				// 将整个文件夹压缩
				ZipUtil zip = new ZipUtil();
				String zipPath = dirPath + ".zip";
				FileUtil.deleteFile(zipPath);
				zip.createZip(zipPath, dirPath);
				attachedFileList.add(zipPath);
			} else {
				content = "您下载的报表数据量过大，请登录商业数据分析系统(http://bi.t.58.com)修改查询条件并重新下载！";
			}
			// 发送
			for (String address : emailAdds) {
				address = address.trim();
				int sendResult = MailUtil.javaMailSend(emailTitle, content,address, attachedFileList);
				if (sendResult == 1) {
					System.out.println("Send ReportSubEmail success! The E-mail ad  is "+ address+ ", The SubMail  ID is "+ vo.getId());
				} else {
					System.out.println("Send ReportSubEmail fail! The E-mail ad  is "+ address+ ", The SubMail  ID is "+ vo.getId());
					MailUtil.javaMailSend("下载邮件发送失败", "下载ID为" + vo.getId()+ ",收件人地址为" + address, "houzuoxin@58.com", null);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			MailUtil.javaMailSend("下载邮件发送程序报错", "下载ID为" + vo.getId(),
					"houzuoxin@58ganji.com", null);
			return 0;
		}
		return 2;
	}
	
	
	public static void main(String[] args) {
		
				try {
					UserSubMailService UserSubMailService = ServiceLocator.get(UserSubMailService.class);
					ScfUtil.initSCF();//SCF初始化 扫包
					List<UserSubMailVo> smList = UserSubMailService.getAllToSendList();//所有未发送的订阅
					List<UserSubMailVo> sendList = new ArrayList<UserSubMailVo>(); //待发送的订阅  
					
					for(UserSubMailVo vo : smList){
						//如果vo正在执行，即还没执行完，则延长5分钟后再次尝试添加
						if(vo.getState()==2)
						{
						  System.out.println("正在执行。。。");
						}else {
							sendList.add(vo);
						}
					}
					
					
					if(null == sendList || sendList.isEmpty()){
						System.out.println("No sub mail have to send !");
					}else{
						int corePoolSize = Runtime.getRuntime().availableProcessors();//CPU个数
						long keepAliveTime = 10; //线程活动保持时间
						LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(sendList.size()); //线程队列
						ThreadPoolExecutor  pool = new ThreadPoolExecutor(corePoolSize/2, corePoolSize, keepAliveTime, TimeUnit.SECONDS, queue);
		//				ExecutorService pool=Executors.newCachedThreadPool();
						for(UserSubMailVo vo : sendList){
							vo.setState(2);
							Thread  thread = new UserSubEmailThread(vo);
							pool.submit(thread);
							vo.setState(3);
						}
						while(true){
							if(UserSubEmailThread.threadDoneCount.get() == sendList.size()){
								pool.shutdown();
								System.out.println("All sub mail has done!");
								break;
							}
						}
					}
					
				} catch (Exception e) {
					e.printStackTrace();
				}
				/*finally{
					System.exit(0);
				}*/
		    }
	
}
